﻿
using IdentityModel;
using Lazy.Captcha.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using RBACProject.Application.User.Dto;
using RBACProject.Domian;
using RBACProject.Repositories;
using RBACProject.Utlity;  
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace RBACProject.Application.User
{
    /// <summary>
    /// 用户服务层
    /// </summary>
    public class UserService : IUserService
    {
        private readonly IConfiguration configuration;

        private readonly ICaptcha _captcha;

        private readonly IBaseRepository<UserModel> User;

        private readonly IBaseRepository<UserRoleModel> Userrole;

        private readonly MyDbContext Db;


        public UserService(IBaseRepository<UserModel> user, IBaseRepository<UserRoleModel> userrole, IConfiguration configuration, ICaptcha captcha, MyDbContext db)
        {
            User = user;
            Userrole = userrole;
            this.configuration = configuration;
            _captcha = captcha;
            Db = db;
        }


        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="model">参数</param>
        /// <returns></returns>
        public async Task<ResultDto<int>> UserRegister(UserModel model)
        {
            model.Password = MD5Helper.Md5(model.Password);         
            await User.InsertAsync(model);
            return new ResultDto<int>
            {
                Result = Result.Success,
                Message="注册成功！",
            };
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ResultDto<UserModelDto>> GetUserLogin(UserLoginDto dto)
        {
            //获取验证码
            var captchaRul = _captcha.Validate(dto.captId, dto.captCode);
            //判断验证码
            if (!captchaRul)
            {
                return new ResultDto<UserModelDto>
                {
                    Result = Result.Failure,
                    Message = "验证码错误,请重新输入！"
                };
            }
            else
            {
                //根据 用户名 获取用户信息
                var data = await User.QueryAsnycEntity(x => x.UserName == dto.UserName);

                //判断是否有当前用户
                if (data == null)
                {
                    return new ResultDto<UserModelDto>
                    {
                        Result = Result.Failure,
                        Message = "没有此用户！"
                    };
                }
                //使用MD5加密 判断dto中的输入的密码与数据库中该用户的MD5密码是否相等如果相等返回正确提示
                //data.Password== dto.Password.Md5();
                else if (data.Password.ToUpper() == dto.Password.Md5().ToUpper())
                {
                    var roleIds = Userrole.QueryAsnycAll().Where(x => x.UserId == data.UserId).Select(m => m.RoleId).ToList();

                    UserModelDto userInfoDto=new UserModelDto();

                    //获取当前用户信息 前端需要存储到Cookie使用
                    userInfoDto.UserId = data.UserId;
                    userInfoDto.UserName = data.UserName;
                    userInfoDto.FullName= data.FullName;
                    userInfoDto.Avatar=data.Avatar;
                    userInfoDto.Email= data.Email;

                    //身份信息认证
                    //写Session或Cookies换成JWT
                    IList<Claim> claims = new List<Claim> {
                            new Claim(JwtClaimTypes.Id,data.UserId.ToString()),
                            new Claim(JwtClaimTypes.Name,data.UserName),
                            new Claim(ClaimTypes.Name,data.UserName),
                            new Claim(ClaimTypes.Role,string.Join(',',roleIds))
                    };
                    //JWT密钥
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:key"]));

                    //算法
                    var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    //过期时间
                    DateTime expires = DateTime.UtcNow.AddMinutes(30);

                    //Payload负载
                    var token = new JwtSecurityToken(
                        issuer: configuration["JwtConfig:Issuer"],
                        audience: configuration["JwtConfig:Audience"],
                        claims: claims,
                        notBefore: DateTime.UtcNow,
                        expires: expires,
                        signingCredentials: cred
                        );

                    var handler = new JwtSecurityTokenHandler();

                    //生成令牌
                    string jwt = handler.WriteToken(token);

                    return new ResultDto<UserModelDto>
                    {
                        Result = Result.Success,
                        Message = "登录成功！",
                        Token = jwt,
                        Data= userInfoDto
                    }; 
                }
                else
                {
                    return new ResultDto<UserModelDto>
                    {
                        Result = Result.Failure,
                        Message = "密码错误！"
                    };
                }
            }
        }


        /// <summary>
        /// 获取全部用户信息并分页
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="totalCount">总行数</param>
        /// <param name="pageCount">分页总数</param>
        /// <returns></returns>
        public List<UserModel> GetUserInfo(string userName, string fullName, int pageIndex, int pageSize, out int totalCount, out int pageCount)
        {
            //查询全部
            var data = User.QueryAsnycAll();
            //根据条件信息
            var query = from u in data
                        where (
                        (string.IsNullOrEmpty(userName) || u.UserName.Contains(userName))
                        && (string.IsNullOrEmpty(fullName) || u.FullName.Contains(fullName))
                        && u.IsDeleted == false)
                        select u;
            //计算
            totalCount = query.Count();
            pageCount = (int)Math.Ceiling(totalCount * 1.0 / pageSize);
            //分页
            query = query.OrderBy(x => x.UserId).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            return query.ToList();
        }


        /// <summary>
        /// 查询  按主键查
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<UserModel> UserQueryById(int id)
        {
            var data = User.QueryAsnycById(id);
            return data;
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ResultDto<int>> DeleteAsync(int id)
        {
            var entity = await User.QueryAsnycById(id);
            entity.IsDeleted = true;
            var data = await User.UpdateAsnyc(entity);
            if (data.IsDeleted == true)
            {
                return new ResultDto<int>
                {
                    Result = Result.Success,
                    Message = "删除成功"
                };
            }
            else
            {
                return new ResultDto<int>
                {
                    Result = Result.Failure,
                    Message = "删除失败"
                };
            }
        }


        /// <summary>
        /// 批量删除用户信息
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<ResultDto<int>> BatchDelUser(List<int> ids)
        {
            var data = await User.QueryWhere(x => ids.Contains(x.UserId));
            using (var tran = Db.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
            {
                try
                {
                    foreach (var item in data)
                    {
                        item.IsDeleted = true;
                        var v = await User.UpdateAsnyc(item);
                    }
                    tran.Commit();
                    return new ResultDto<int>
                    {
                        Result = Result.Success,
                        Message = "批量删除成功！",
                    };
                }
                catch (Exception)
                {
                    tran.Rollback();
                    return new ResultDto<int>
                    {
                        Result = Result.Success,
                        Message = "批量删除失败！",
                    };
                    throw;
                }
            }
        }


        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultDto<UserModel>> UpdateUser(UserModel model)
        {
            var d = User.QueryAsnycAll().Where(x => x.UserName == model.UserName && x.UserId==model.UserId);
            if (d.Count()> 0) 
            {
                return new ResultDto<UserModel>
                {
                    Result = Result.Success,
                    Message = "当前用户已经存在。。。",
                };
            }
            var data = await User.UpdateAsnyc(model);
            return new ResultDto<UserModel>
            {
                Result = Result.Success,
                Message = "修改成功!",
            };
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="newPassword">新密码</param>
        /// <param name="id">用户id</param>
        /// <returns></returns>
        public async Task<ResultDto<UserModel>> ResetUserPassword(string newPassword,int id)
        {
            var data = User.QueryAsnycAll().FirstOrDefault(x=>x.UserId==id);
            data.Password = MD5Helper.Md5(newPassword);
            await User.UpdateAsnyc(data); 
            return new ResultDto<UserModel>
            {
                Result = Result.Success,
                Message = "密码重置成功！",
            };
        }



    }
}
